﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using RawLevelFormat;
using Microsoft.Xna.Framework.Audio;

namespace theguineasyndrome
{
    public class GameMode : AppMode
    {
        private Character player;

        // weapons
        private WaterWeapon water;
        private FireWeapon fire;
        private PortalWeapon portal;
        private PaintWeapon paint;

        private List<Weapon> weapons;

        // clouds
        private Clouds clouds;
        private Texture2D cloudTexture;

        // score
        private Score score;
        private SpriteFont scoreFont;
        private SpriteFont bigScoreFont;

        // textures & sounds
        private Texture2D backgroundTexture;

        private Texture2D gameoverTexture;
        private Vector2 gameoverOrigin;

        private Texture2D levelFinishedTexture;
        private Vector2 levelFinishedOrigin;

        private Texture2D gameFinishedTexture;
        private Vector2 gameFinishedOrigin;

        private Texture2D pushspaceTexture;
        private Vector2 pushspaceOrigin;

        // water
        private Texture2D[] waterDropTextures;
        private Texture2D[] waterFlakeTextures;

        private SoundEffect waterPrimarySound;

        // fire
        private Texture2D[] fireDropTextures;
        private Texture2D[] fireFlakeTextures;

        private SoundEffect firePrimarySound;
        private SoundEffect cracklingSound;

        // portal
        private Texture2D blueDropTexture;
        private Texture2D orangeDropTexture;

        private Texture2D bluePortalTexture;
        private Texture2D orangePortalTexture;

        private SoundEffect portalSound;

        // paint
        private Texture2D[] paintSplashTextures;

        // carots
        private Texture2D carotTexture;
        private Texture2D marioCarotTexture;
        private Texture2D portalCarotTexture;
        private Texture2D pyroCarotTexture;

        private SoundEffect carotSound;

        private SoundEffect enemySound;

        // recharge time texture
        private Texture2D redbarTexture;

        private bool gameOver;
        private bool levelFinished;
        private bool gameFinished;
        private int currentLevel;

        // levels
        levels.Levels levels;

        public GameMode(TheGuineaSyndromeGame game, GraphicsDevice graphicsDevice, ContentManager content, GameWindow Window)
            : base(game, graphicsDevice, content, Window)
        {
            gameFinished = false;
        }

        public override bool isFullScreen()
        {
            return false;
        }

        public override void Initialize()
        {
            base.Initialize();

            water = new WaterWeapon(waterFlakeTextures, waterDropTextures, waterPrimarySound);
            fire = new FireWeapon(fireFlakeTextures, fireDropTextures, firePrimarySound, cracklingSound);
            portal = new PortalWeapon(blueDropTexture, orangeDropTexture, bluePortalTexture, orangePortalTexture, portalSound);
            paint = new PaintWeapon(waterFlakeTextures, waterDropTextures, paintSplashTextures);

            weapons = new List<Weapon>();

            weapons.Add(water);
            weapons.Add(fire);
            weapons.Add(portal);
            weapons.Add(paint);

            levels = new levels.Levels(this, content, water, fire, portal, paint);
            loadLevel(0);
        }

        public void reloadLevel()
        {
            loadLevel(currentLevel);
        }

        public void finishLevel()
        {
            levelFinished = true;
        }

        private bool isLastLevel()
        {
            return levels.isLastLevel(currentLevel);
        }

        private void loadNextLevel()
        {
            levels.finish(currentLevel, score);
            loadLevel(currentLevel + 1);
        }

        public void loadLevel(int n)
        {
            currentLevel = n;
            gameOver = false;
            levelFinished = false;
            setLevel(levels.load(n));

            foreach (Weapon weapon in weapons)
                weapon.clear();

            clouds = new Clouds(level, cloudTexture);
            fire.setClouds(clouds);

            score = new Score((int)currentTime.TotalGameTime.TotalMilliseconds, scoreFont, carotTexture, level.getNumCarots());

            player = new Character(this, level, clouds, level.getPointMarkPosition("start"), new RabbitModel(content, null), score, redbarTexture, carotSound, enemySound);
            camera.setCenter(player.Center);
        }

        public void over()
        {
            gameOver = true;
        }

        public override void LoadContent()
        {
            base.LoadContent();

            cloudTexture = content.Load<Texture2D>("images/cloud");

            backgroundTexture = content.Load<Texture2D>("images/background");

            gameoverTexture = content.Load<Texture2D>("images/gameover");
            gameoverOrigin = new Vector2(gameoverTexture.Width, gameoverTexture.Height) / 2;

            levelFinishedTexture = content.Load<Texture2D>("images/levelfinished");
            levelFinishedOrigin = new Vector2(levelFinishedTexture.Width, levelFinishedTexture.Height) / 2;

            gameFinishedTexture = content.Load<Texture2D>("images/gamefinished");
            gameFinishedOrigin = new Vector2(gameFinishedTexture.Width, gameFinishedTexture.Height) / 2;

            pushspaceTexture = content.Load<Texture2D>("images/pushspace");
            pushspaceOrigin = new Vector2(pushspaceTexture.Width, pushspaceTexture.Height) / 2;

            // water
            waterFlakeTextures = new Texture2D[] {
                content.Load<Texture2D>("images/weapons/water/flake1"),
                content.Load<Texture2D>("images/weapons/water/flake2"),
                content.Load<Texture2D>("images/weapons/water/flake3"),
                content.Load<Texture2D>("images/weapons/water/flake4")
            };
            waterDropTextures = new Texture2D[] {
                content.Load<Texture2D>("images/weapons/water/drop1"),
                content.Load<Texture2D>("images/weapons/water/drop2")
            };
            waterPrimarySound = content.Load<SoundEffect>("sounds/water");

            // fire
            fireFlakeTextures = new Texture2D[] {
                content.Load<Texture2D>("images/weapons/fire/flame1"),
                content.Load<Texture2D>("images/weapons/fire/flame2"),
                content.Load<Texture2D>("images/weapons/fire/flame3"),
                content.Load<Texture2D>("images/weapons/fire/flame4"),
                content.Load<Texture2D>("images/weapons/fire/flame5"),
                content.Load<Texture2D>("images/weapons/fire/flame6"),
                content.Load<Texture2D>("images/weapons/fire/flame7"),
                content.Load<Texture2D>("images/weapons/fire/flame8")
            };
            fireDropTextures = new Texture2D[] { // only the smallest textures
                content.Load<Texture2D>("images/weapons/fire/flame2"),
                content.Load<Texture2D>("images/weapons/fire/flame4"),
                content.Load<Texture2D>("images/weapons/fire/flame6"),
                content.Load<Texture2D>("images/weapons/fire/flame8")
            };
            firePrimarySound = content.Load<SoundEffect>("sounds/fire");
            cracklingSound = content.Load<SoundEffect>("sounds/crackling");

            // portal
            blueDropTexture = content.Load<Texture2D>("images/weapons/portal/bluedrop");
            orangeDropTexture = content.Load<Texture2D>("images/weapons/portal/orangedrop");

            bluePortalTexture = content.Load<Texture2D>("images/weapons/portal/blueportal");
            orangePortalTexture = content.Load<Texture2D>("images/weapons/portal/orangeportal");

            portalSound = content.Load<SoundEffect>("sounds/portal");

            // paint
            paintSplashTextures = new Texture2D[] {
                content.Load<Texture2D>("images/weapons/paint/splash1"),
                content.Load<Texture2D>("images/weapons/paint/splash2"),
                content.Load<Texture2D>("images/weapons/paint/splash3")
            };

            // carots
            carotTexture = content.Load<Texture2D>("images/carots/carot");
            marioCarotTexture = content.Load<Texture2D>("images/carots/mario");
            portalCarotTexture = content.Load<Texture2D>("images/carots/portal");
            pyroCarotTexture = content.Load<Texture2D>("images/carots/pyro");

            carotSound = content.Load<SoundEffect>("sounds/carot");

            enemySound = content.Load<SoundEffect>("sounds/enemy");

            // score
            scoreFont = content.Load<SpriteFont>("fonts/score");
            bigScoreFont = content.Load<SpriteFont>("fonts/bigscore");

            // recharge time
            redbarTexture = content.Load<Texture2D>("images/redbar");
        }

        public override void UnloadContent()
        {
            base.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            if (isJustPressed(Keys.Escape) || (isJustPressed(Keys.Space) && gameFinished))
                game.setMode(new MenuMode(game, graphicsDevice, content, window));

            level.Update(gameTime);

            if (gameOver)
            {
                if (isJustPressed(Keys.Space))
                    reloadLevel();
            }
            else if (levelFinished)
            {
                if (isJustPressed(Keys.Space))
                {
                    if (isLastLevel())
                    {
                        gameFinished = true;
                        levels.finish(currentLevel, score);
                    }
                    else
                        loadNextLevel();
                }
            }
            else
            {
                Vector2 mouse = camera.getRelative(getPointer());

                player.Update(gameTime, mouse);

                camera.moveCenterTo(new Vector2(player.CenterX, player.Top));

                score.Update(gameTime);
            }

            foreach (Weapon weapon in weapons)
                weapon.Update(gameTime);

            clouds.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            level.prepareDrawing(camera);
            clouds.queueDrawing(camera);

            if (!gameOver)
                player.queueDrawing(camera);

            foreach (Weapon weapon in weapons)
                weapon.queueDrawing(camera);

            // background
            spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.LinearWrap, DepthStencilState.Default, RasterizerState.CullNone);
            spriteBatch.Draw(backgroundTexture, screenRectangle, Color.White);
            spriteBatch.End();

            spriteBatch.Begin();
            // backgrounds
            level.drawBackgrounds(spriteBatch, camera);
            // level
            level.drawObjects(spriteBatch, camera);
            // foreground
            level.drawForegrounds(spriteBatch, camera);

            if (gameFinished)
            {
                spriteBatch.Draw(gameFinishedTexture, new Vector2(camera.Width, camera.Height) / 2, null, Color.White, 0, gameFinishedOrigin, 1, SpriteEffects.None, 0);
                spriteBatch.Draw(pushspaceTexture, new Vector2(camera.Width, camera.Height + 200) / 2, null, Color.White, 0, pushspaceOrigin, 1, SpriteEffects.None, 0);

                Score finalScore = levels.getFinalScore();

                string strScore = "Score total : " + finalScore.TotalScore;
                Vector2 scoreSize = bigScoreFont.MeasureString(strScore);
                spriteBatch.DrawString(bigScoreFont, strScore, new Vector2(camera.Width, camera.Height + 400) / 2 - scoreSize / 2, Color.Black);

                Color carotsColor = Color.DarkOrange;

                if (finalScore.NumCollectedCarots == finalScore.NumCarots)
                    carotsColor = Color.Green;

                string strCarots = "Carottes collectees : " + finalScore.NumCollectedCarots + "/" + finalScore.NumCarots;
                Vector2 carotsSize = bigScoreFont.MeasureString(strCarots);
                spriteBatch.DrawString(bigScoreFont, strCarots, new Vector2(camera.Width, camera.Height + 500) / 2 - carotsSize / 2, carotsColor);
            }
            else if (gameOver)
            {
                spriteBatch.Draw(gameoverTexture, new Vector2(camera.Width, camera.Height) / 2, null, Color.White, 0, gameoverOrigin, 1, SpriteEffects.None, 0);
                spriteBatch.Draw(pushspaceTexture, new Vector2(camera.Width, camera.Height + 200) / 2, null, Color.White, 0, pushspaceOrigin, 1, SpriteEffects.None, 0);
            }
            else if (levelFinished)
            {
                spriteBatch.Draw(levelFinishedTexture, new Vector2(camera.Width, camera.Height) / 2, null, Color.White, 0, levelFinishedOrigin, 1, SpriteEffects.None, 0);
                spriteBatch.Draw(pushspaceTexture, new Vector2(camera.Width, camera.Height + 200) / 2, null, Color.White, 0, pushspaceOrigin, 1, SpriteEffects.None, 0);

                string strScore = "Score : " + score.TotalScore;
                Vector2 scoreSize = bigScoreFont.MeasureString(strScore);
                spriteBatch.DrawString(bigScoreFont, strScore, new Vector2(camera.Width, camera.Height + 500) / 2 - scoreSize / 2, Color.Black);
            }
            else
            {
                score.Draw(spriteBatch, camera);
                player.DrawRechargeTimes(spriteBatch, camera);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
